﻿using DevExpress.Xpf.Core;
using DXApp.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shell;

namespace DXApp.Wpf
{
    /// <summary>
    /// 定义基础窗体
    /// </summary>
    [TemplatePart(Name = CustomLayoutRoot, Type = typeof(UIElement))]
    public class XWindow : ThemedWindow, IMaskable
    {
        public const string CustomLayoutRoot = "PART_layoutRoot";
        /// <summary>
        /// 窗体内容
        /// </summary>
        private UIElement _layoutRoot;
        /// <summary>
        /// 遮罩装饰器
        /// </summary>
        private ShadeAdorner ShadeAdorner { get; set; }

        #region DependencyProperties

        /// <summary>
        /// 标题栏高度
        /// </summary>
        public static readonly DependencyProperty TitleHeightProperty = DependencyProperty.Register("TitleHeight", typeof(double), typeof(XWindow));
        /// <summary>
        /// 标题栏高度
        /// </summary>
        public double TitleHeight { get => (double)GetValue(TitleHeightProperty); set => SetValue(TitleHeightProperty, value); }

        /// <summary>
        /// 标题栏背景色
        /// </summary>
        public static readonly DependencyProperty TitleBackgroundProperty = DependencyProperty.Register("TitleBackground", typeof(Brush), typeof(XWindow));
        /// <summary>
        /// 标题栏背景色
        /// </summary>
        public Brush TitleBackground { get => (Brush)GetValue(TitleBackgroundProperty); set => SetValue(TitleBackgroundProperty, value); }

        /// <summary>
        /// 标题栏前景色
        /// </summary>
        public static readonly DependencyProperty TitleForegroundProperty = DependencyProperty.Register("TitleForeground", typeof(Brush), typeof(XWindow));
        /// <summary>
        /// 标题栏前景色
        /// </summary>
        public Brush TitleForeground { get => (Brush)GetValue(TitleForegroundProperty); set => SetValue(TitleForegroundProperty, value); }

        /// <summary>
        /// 标题栏字体大小
        /// </summary>
        public static readonly DependencyProperty TitleFontSizeProperty = DependencyProperty.Register("TitleFontSize", typeof(double), typeof(XWindow));
        /// <summary>
        /// 标题栏字体大小
        /// </summary>
        public double TitleFontSize { get => (double)GetValue(TitleFontSizeProperty); set => SetValue(TitleFontSizeProperty, value); }

        /// <summary>
        /// 标题栏Icon
        /// </summary>
        public static readonly DependencyProperty TitleIconProperty = DependencyProperty.Register("TitleIcon", typeof(ImageSource), typeof(XWindow));
        /// <summary>
        /// 标题栏Icon
        /// </summary>
        public ImageSource TitleIcon { get => (ImageSource)GetValue(TitleIconProperty); set => SetValue(TitleIconProperty, value); }

        /// <summary>
        /// 标题内容
        /// </summary>
        public static readonly DependencyProperty TitleContentProperty = DependencyProperty.Register("TitleContent", typeof(object), typeof(XWindow));
        /// <summary>
        /// 标题内容
        /// </summary>
        public object TitleContent { get => GetValue(TitleContentProperty); set => SetValue(TitleContentProperty, value); }

        /// <summary>
        /// 标题内容数据模板
        /// </summary>
        public static readonly DependencyProperty TitleContentTemplateProperty = DependencyProperty.Register("TitleContentTemplate", typeof(DataTemplate), typeof(XWindow));
        /// <summary>
        /// 标题内容数据模板
        /// </summary>
        public DataTemplate TitleContentTemplate { get => (DataTemplate)GetValue(TitleContentTemplateProperty); set => SetValue(TitleContentTemplateProperty, value); }

        /// <summary>
        /// 只显示关闭
        /// </summary>
        public static readonly DependencyProperty ShowCloseButtonOnlyProperty = DependencyProperty.Register("ShowCloseButtonOnly", typeof(bool), typeof(XWindow));
        /// <summary>
        /// 只显示关闭
        /// </summary>
        public bool ShowCloseButtonOnly { get => (bool)GetValue(ShowCloseButtonOnlyProperty); set => SetValue(ShowCloseButtonOnlyProperty, value); }

        /// <summary>
        /// 保持最大化（窗口只能最小化和最大化，不能正常化）
        /// </summary>
        public static readonly DependencyProperty KeepMaximizedProperty = DependencyProperty.Register("KeepMaximized", typeof(bool), typeof(XWindow), new PropertyMetadata(OnKeepMaximizedPropertyChanged));
        /// <summary>
        /// 保持最大化（窗口只能最小化和最大化，不能正常化）
        /// </summary>
        public bool KeepMaximized { get => (bool)GetValue(KeepMaximizedProperty); set => SetValue(KeepMaximizedProperty, value); }

        private static readonly DependencyPropertyDescriptor descriptorWindowState = DependencyPropertyDescriptor.FromProperty(WindowStateProperty, typeof(Window));
        private static void OnKeepMaximizedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is Window win)
            {
                if ((bool)e.NewValue)
                {
                    descriptorWindowState.AddValueChanged(win, OnMaximizedPropertyChanged);

                    if (win.WindowState == WindowState.Normal)
                        win.WindowState = WindowState.Maximized;
                }
                else
                    descriptorWindowState.RemoveValueChanged(win, OnMaximizedPropertyChanged);

                void OnMaximizedPropertyChanged(object sender, EventArgs args)
                {
                    var w = (Window)sender;

                    if (w.WindowState == WindowState.Normal)
                    {
                        w.Dispatcher.InvokeAsync(() =>
                        {
                            if (w.WindowState == WindowState.Normal)
                                w.WindowState = WindowState.Maximized;
                        });
                    }
                }
            }
        }

        #endregion


        static XWindow()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(XWindow), new FrameworkPropertyMetadata(typeof(XWindow)));
        }
        public XWindow()
        {
            CommandBindings.Add(new CommandBinding(SystemCommands.CloseWindowCommand, CloseWindow));
            CommandBindings.Add(new CommandBinding(SystemCommands.MaximizeWindowCommand, MaximizeWindow, CanResizeWindow));
            CommandBindings.Add(new CommandBinding(SystemCommands.MinimizeWindowCommand, MinimizeWindow, CanMinimizeWindow));
            CommandBindings.Add(new CommandBinding(SystemCommands.RestoreWindowCommand, RestoreWindow, CanResizeWindow));
            CommandBindings.Add(new CommandBinding(SystemCommands.ShowSystemMenuCommand, ShowSystemMenu));
            SizeChanged += XWindow_SizeChanged;
        }

        private void XWindow_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            MaxHeight = SystemParameters.VirtualScreenHeight;
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            //
            _layoutRoot = GetTemplateChild(CustomLayoutRoot) as UIElement;
        }

        protected override void OnContentRendered(EventArgs e)
        {
            base.OnContentRendered(e); //OnSourceInitialized /OnContentRendered
            if (SizeToContent == SizeToContent.WidthAndHeight && WindowChrome.GetWindowChrome(this) != null)
            {
                InvalidateMeasure(); //处理黑边框问题
            }
        }

        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
        }

        #region Window Commands

        private void CanResizeWindow(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = ResizeMode == ResizeMode.CanResize || ResizeMode == ResizeMode.CanResizeWithGrip;
        }

        private void CanMinimizeWindow(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = ResizeMode != ResizeMode.NoResize;
        }

        private void CloseWindow(object sender, ExecutedRoutedEventArgs e)
        {
            Close();
            //SystemCommands.CloseWindow(this);
        }

        private void MaximizeWindow(object sender, ExecutedRoutedEventArgs e)
        {
            SystemCommands.MaximizeWindow(this);
        }

        private void MinimizeWindow(object sender, ExecutedRoutedEventArgs e)
        {
            SystemCommands.MinimizeWindow(this);
        }

        private void RestoreWindow(object sender, ExecutedRoutedEventArgs e)
        {
            SystemCommands.RestoreWindow(this);
        }

        private void ShowSystemMenu(object sender, ExecutedRoutedEventArgs e)
        {
            var element = e.OriginalSource as FrameworkElement;
            if (element == null)
                return;

            var point = WindowState == WindowState.Maximized ? new Point(0, element.ActualHeight)
                : new Point(Left + BorderThickness.Left, element.ActualHeight + Top + BorderThickness.Top);
            point = element.TransformToAncestor(this).Transform(point);
            SystemCommands.ShowSystemMenu(this, point);
        }

        #endregion


        /// <summary>
        /// 展示弹框
        /// </summary>
        /// <param name="window">父窗口</param>
        /// <returns>指定活动是否被接受</returns>
        public bool? ShowDialog(Window window)
        {
            return ShowDialog(window, WindowAlignment.Middle);
        }

        /// <summary>
        /// 展示弹框
        /// </summary>
        /// <returns></returns>
        public bool? ShowCustomDialog()
        {
            Window window = null;
            foreach (Window item in Application.Current.Windows)
            {
                if (item.IsActive)
                {
                    window = item;
                    break;
                }
            }
            return ShowDialog(window, WindowAlignment.Middle);
        }

        /// <summary>
        /// 展示弹框
        /// </summary>
        /// <param name="window">父窗口</param>
        /// <returns>指定活动是否被接受</returns>
        public bool? ShowCustomDialog(WindowAlignment windowAlignment)
        {
            Window window = null;
            foreach (Window item in Application.Current.Windows)
            {
                if (item.IsActive)
                {
                    window = item;
                    break;
                }
            }
            return ShowDialog(window, windowAlignment);
        }

        /// <summary>
        /// 展示弹框
        /// </summary>
        /// <param name="window">父窗口</param>
        /// <returns>指定活动是否被接受</returns>
        public bool? ShowDialog(Window window, WindowAlignment windowAlignment)
        {
            if (window == null)
            {
                return ShowDialog();
            }

            if (window.IsVisible)
            {
                Owner = window;
            }

            double leftOffset = 0;
            double topOffset = 0;
            switch (windowAlignment)
            {
                case WindowAlignment.TopLeft:
                    leftOffset = 0;
                    topOffset = 0;
                    break;
                case WindowAlignment.TopCenter:
                    leftOffset = (window.Width - Width) / 2;
                    topOffset = 0;
                    break;
                case WindowAlignment.TopRight:
                    leftOffset = window.Width - Width;
                    topOffset = 0;
                    break;
                case WindowAlignment.CenterLeft:
                    leftOffset = 0;
                    topOffset = (window.Height - Height) / 2;
                    break;
                case WindowAlignment.Middle:
                    WindowStartupLocation = window.IsVisible ? WindowStartupLocation.CenterOwner : WindowStartupLocation.CenterScreen;
                    break;
                case WindowAlignment.CenterRight:
                    leftOffset = window.Width - Width;
                    topOffset = (window.Height - Height) / 2;
                    break;
                case WindowAlignment.BottomLeft:
                    leftOffset = 0;
                    topOffset = window.Height - Height;
                    break;
                case WindowAlignment.BottomCenter:
                    leftOffset = (window.Width - Width) / 2;
                    topOffset = window.Height - Height;
                    break;
                case WindowAlignment.BottomRight:
                    leftOffset = window.Width - Width;
                    topOffset = window.Height - Height;
                    break;
                default:
                    break;
            }

            Left = window.Left + leftOffset;
            Top = window.Top + topOffset;
            if (window is IMaskable maskable)
            {
                maskable.ShowShade();
            }

            return ShowDialog();
        }



        /// <summary>
        /// 显示遮罩
        /// </summary>
        public void ShowShade()
        {
            if (_layoutRoot != null)
            {
                ShadeAdorner = _layoutRoot.GetOrAddAdorner<ShadeAdorner>();
                ShadeAdorner?.SetVisibility(Visibility.Visible);
            }
        }

        /// <summary>
        /// 隐藏遮罩
        /// </summary>
        public void HideShade()
        {
            ShadeAdorner?.SetVisibility(Visibility.Collapsed);
        }
    }

}
